<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>新旧生命周期对比</title>
  </head>
  <body>
    <div id="test"></div>

    <script src="../js/17.0.1/react.development.js"></script>
    <script src="../js/17.0.1/react-dom.development.js"></script>
    <script src="../js/17.0.1/babel.min.js"></script>

    <script type="text/babel">
      // 创建类式组件
      class Count extends React.Component {
        constructor(props) {
          console.log('constructor')
          super(props)

          // 初始化状态
          this.state = {
            count: 0
          }
        }

        addCount = () => {
          this.setState({
            count: this.state.count + 1
          })
        }

        delCom = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById('test'))
        }

        forceUpdateCom = () => {
          // 注意：强制更新不更改任何状态数据
          this.forceUpdate()
        }

        // 组件将要挂载时调用
        UNSAFE_componentWillMount() {
          console.log('UNSAFE_componentWillMount')
        }

        // 组件挂载完毕后调用
        componentDidMount() {
          console.log('componentDidMount')
        }

        // 组件将要卸载时调用
        componentWillUnmount() {
          console.log('componentWillUnmount')
        }

        // 组件是否应该更新
        // 注意：如果写当前钩子时一定要加返回值（Boolean），false 则阻止组件更新
        shouldComponentUpdate() {
          console.log('shouldComponentUpdate')
          return true
        }

        // 组件将要更新时加载
        UNSAFE_componentWillUpdate() {
          console.log('UNSAFE_componentWillUpdate')
        }

        // 组件更新完毕后加载
        componentDidUpdate() {
          console.log('componentDidUpdate')
        }

        // 组价初次渲染、更新时调用
        render() {
          console.log('render')
          return (
            <div>
              <h2>当前求和：{this.state.count}</h2>
              <button onClick={this.addCount}>点我+1</button>
              <button onClick={this.delCom}>卸载</button>
              <button onClick={this.forceUpdateCom}>强制更新</button>
            </div>
          )
        }
      }

      class A extends React.Component {
        state = {
          carName: '宝马'
        }

        changeCar = () => {
          this.setState({
            carName: '奔驰'
          })
        }

        delCom = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById('test'))
        }

        // 组件将要挂载时调用
        UNSAFE_componentWillMount() {
          console.log('A-->UNSAFE_componentWillMount')
        }

        // 组件挂载完毕后调用
        componentDidMount() {
          console.log('A-->componentDidMount')
        }

        // 组件将要卸载时调用
        componentWillUnmount() {
          console.log('A-->componentWillUnmount')
        }

        // 组件是否应该更新
        // 注意：如果写当前钩子时一定要加返回值（Boolean），false 则阻止组件更新
        shouldComponentUpdate() {
          console.log('A-->shouldComponentUpdate')
          return true
        }

        // 组件将要更新时加载
        UNSAFE_componentWillUpdate() {
          console.log('A-->UNSAFE_componentWillUpdate')
        }

        // 组件更新完毕后加载
        componentDidUpdate() {
          console.log('A-->componentDidUpdate')
        }

        render() {
          console.log('A-->render')
          return (
            <div>
              <div>A</div>
              <button onClick={this.changeCar}>我要换车</button>
              <button onClick={this.delCom}>卸载</button>
              <B carName={this.state.carName} />
            </div>
          )
        }
      }

      class B extends React.Component {
        // 组件将要接收父组件传递的 props 钩子
        // 注意：初次渲染时不算
        UNSAFE_componentWillReceiveProps(props) {
          console.log('B-->UNSAFE_componentWillReceiveProps', props)
        }

        // 组件将要挂载时调用
        UNSAFE_componentWillMount() {
          console.log('B-->UNSAFE_componentWillMount')
        }

        // 组件挂载完毕后调用
        componentDidMount() {
          console.log('B-->componentDidMount')
        }

        // 组件将要卸载时调用
        componentWillUnmount() {
          console.log('B-->componentWillUnmount')
        }

        // 组件是否应该更新
        // 注意：如果写当前钩子时一定要加返回值（Boolean），false 则阻止组件更新
        shouldComponentUpdate() {
          console.log('B-->shouldComponentUpdate')
          return true
        }

        // 组件将要更新时加载
        UNSAFE_componentWillUpdate() {
          console.log('B-->UNSAFE_componentWillUpdate')
        }

        // 组件更新完毕后加载
        componentDidUpdate() {
          console.log('B-->componentDidUpdate')
        }

        render() {
          console.log('B-->render')
          return <div>我就收到的车的名字是{this.props.carName}</div>
        }
      }

      ReactDOM.render(<A />, document.getElementById('test'))

      // 注意：
      // 旧生命周期与新生命周期对比发现：
      // 旧版本即将废弃的有：componentWillMount/componentWillReceiveProps/componentWillUpdate
      // 新版本新增的有：getDerivedStateFromProps/getSnapshotBeforeUpdate（几乎不需要考虑使用）
    </script>
  </body>
</html>
